#!/usr/bin/env python3
import os
import sys
import json
import shutil
import subprocess
from pathlib import Path
import gi
from PIL import Image  # 用于处理图片尺寸

# 确保GTK 3和相关库被正确导入
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib, Pango

class TranslationManager:
    """语言翻译管理器，负责加载和管理翻译文件"""
    def __init__(self, app):
        self.app = app
        self.languages_dir = self.app.config_dir / 'languages'
        self.current_language = 'english'  # 默认语言
        self.translations = {}
        
        # 确保语言目录存在
        self.languages_dir.mkdir(parents=True, exist_ok=True)
        
        # 初始化默认语言文件
        self.initialize_default_languages()
        
        # 加载保存的语言设置
        self.load_language_setting()
        
        # 加载当前语言的翻译
        self.load_translations()
    
    def initialize_default_languages(self):
        """初始化默认的语言文件（如果不存在）"""
        # 英文语言文件
        english_file = self.languages_dir / 'english.json'
        if not english_file.exists():
            with open(english_file, 'w', encoding='utf-8') as f:
                json.dump({
                    "app_title": "PyDOSBox Frontend",
                    "add_game": "Add Game",
                    "list_view": "List View",
                    "grid_view": "Grid View",
                    "refresh": "Refresh",
                    "settings": "Settings",
                    "about": "About",
                    "edit_config": "Edit Config",
                    "edit": "Edit",
                    "hide_game": "Hide Game",
                    "unhide_game": "Unhide Game",
                    "edit_game": "Edit Game",
                    "launch_game": "Launch Game",
                    "total_games": "Total games: {count}",
                    
                    # 统计相关
                    "statistics_tab": "Statistics",
                    "total_games_stats": "Total games: {count}",
                    "total_space_used": "Total space used: {size} MB",
                    "game_size": "Size (MB)",
                    "including_hidden_games": "total including hidden games",
                    
                    # 添加游戏对话框
                    "add_new_game": "Add New Game",
                    "id_internal": "ID (internal):",
                    "name": "Name:",
                    "game_directory": "Game directory:",
                    "config_file": "Config file:",
                    "cover_image": "Cover image:",
                    "browse": "Browse...",
                    "cancel": "Cancel",
                    "add": "Add",
                    "required_fields": "ID, Name and Game directory are required",
                    "invalid_directory": "Invalid game directory",
                    "image_files": "Image files",
                    "select": "Select",
                    "stored_in": "stored in",
                    
                    # 编辑游戏对话框
                    "edit_game_title": "Edit {game_name}",
                    "hide_this_game": "Hide this game",
                    
                    # 设置对话框
                    "settings_title": "Settings",
                    "basic_tab": "Basic",
                    "view_tab": "View",
                    "language_tab": "Language",
                    "show_hidden_games": "Show hidden games",
                    "default_view": "Default view:",
                    "show_game_list": "Show game list",
                    "show_game_grid": "Show game grid",
                    "games_directory": "Games directory:",
                    "dosbox_path": "DOSBox path:",
                    "save": "Save",
                    "select_language": "Select language:",
                    "language_files_stored_in": "Language files stored in",
                    
                    # 关于对话框
                    "about_title": "About PyDOSBox",
                    "version": "Version 1.5",
                    "copyright": "Copyright © 2023 PyDOSBox Developers",
                    "description": "A simple frontend for DOSBox to manage and launch your DOS games collection.",
                    "ok": "OK",
                    
                    # 错误消息
                    "dosbox_not_found": "DOSBox not found",
                    "dosbox_not_found_msg": "Please install DOSBox or configure its path in settings.",
                    "error": "Error",
                    "could_not_create_config": "Could not create default config file",
                    "error_launching_game": "Error launching game",
                    "error_opening_editor": "Error opening editor"
                }, f, indent=2, ensure_ascii=False)
        
        # 中文语言文件 - 修复了隐藏游戏统计的翻译
        chinese_file = self.languages_dir / 'chinese.json'
        if not chinese_file.exists():
            with open(chinese_file, 'w', encoding='utf-8') as f:
                json.dump({
                    "app_title": "PyDOSBox 前端",
                    "add_game": "添加游戏",
                    "list_view": "列表视图",
                    "grid_view": "网格视图",
                    "refresh": "刷新",
                    "settings": "设置",
                    "about": "关于",
                    "edit_config": "编辑配置",
                    "edit": "编辑",
                    "hide_game": "隐藏游戏",
                    "unhide_game": "显示游戏",
                    "edit_game": "编辑游戏",
                    "launch_game": "启动游戏",
                    "total_games": "共计 {count} 个游戏",
                    
                    # 统计相关 - 新增了including_hidden_games的翻译
                    "statistics_tab": "统计",
                    "total_games_stats": "共计有 {count} 个游戏",
                    "total_space_used": "共占用 {size} MB 空间",
                    "game_size": "容量 (MB)",
                    "including_hidden_games": "含隐藏游戏总数",
                    
                    # 添加游戏对话框
                    "add_new_game": "添加新游戏",
                    "id_internal": "ID (内部使用):",
                    "name": "名称:",
                    "game_directory": "游戏目录:",
                    "config_file": "配置文件:",
                    "cover_image": "封面图片:",
                    "browse": "浏览...",
                    "cancel": "取消",
                    "add": "添加",
                    "required_fields": "ID、名称和游戏目录为必填项",
                    "invalid_directory": "无效的游戏目录",
                    "image_files": "图片文件",
                    "select": "选择",
                    "stored_in": "存储在",
                    
                    # 编辑游戏对话框
                    "edit_game_title": "编辑 {game_name}",
                    "hide_this_game": "隐藏此游戏",
                    
                    # 设置对话框
                    "settings_title": "设置",
                    "basic_tab": "基本",
                    "view_tab": "视图",
                    "language_tab": "语言",
                    "show_hidden_games": "显示隐藏的游戏",
                    "default_view": "默认视图:",
                    "show_game_list": "显示游戏列表",
                    "show_game_grid": "显示游戏网格",
                    "games_directory": "游戏目录:",
                    "dosbox_path": "DOSBox路径:",
                    "save": "保存",
                    "select_language": "选择语言:",
                    "language_files_stored_in": "语言文件存储在",
                    
                    # 关于对话框
                    "about_title": "关于 PyDOSBox",
                    "version": "版本 1.5",
                    "copyright": "版权所有 © 2023 PyDOSBox 开发者",
                    "description": "一个简单的DOSBox前端，用于管理和启动您的DOS游戏集合。",
                    "ok": "确定",
                    
                    # 错误消息
                    "dosbox_not_found": "未找到DOSBox",
                    "dosbox_not_found_msg": "请安装DOSBox或在设置中配置其路径。",
                    "error": "错误",
                    "could_not_create_config": "无法创建默认配置文件",
                    "error_launching_game": "启动游戏时出错",
                    "error_opening_editor": "打开编辑器时出错"
                }, f, indent=2, ensure_ascii=False)
    
    def load_language_setting(self):
        """加载保存的语言设置"""
        config_file = self.app.config_dir / 'config.json'
        if config_file.exists():
            try:
                with open(config_file, 'r') as f:
                    config = json.load(f)
                    if 'language' in config:
                        self.current_language = config['language']
            except Exception as e:
                print(f"Error loading language setting: {e}")
    
    def save_language_setting(self):
        """保存语言设置"""
        config_file = self.app.config_dir / 'config.json'
        try:
            config = {}
            if config_file.exists():
                with open(config_file, 'r') as f:
                    config = json.load(f)
            
            config['language'] = self.current_language
            
            with open(config_file, 'w') as f:
                json.dump(config, f, indent=2)
        except Exception as e:
            print(f"Error saving language setting: {e}")
    
    def load_translations(self):
        """加载当前语言的翻译，增加错误处理和默认值"""
        lang_file = self.languages_dir / f"{self.current_language}.json"
        default_translations = {}
        
        # 先加载英文作为基础默认值
        try:
            with open(self.languages_dir / 'english.json', 'r', encoding='utf-8') as f:
                default_translations = json.load(f)
        except Exception as e:
            print(f"Error loading default english translations: {e}")
        
        # 尝试加载指定语言
        if lang_file.exists():
            try:
                with open(lang_file, 'r', encoding='utf-8') as f:
                    lang_translations = json.load(f)
                    # 合并翻译，用指定语言覆盖默认值，但保留所有默认条目
                    self.translations = {**default_translations,** lang_translations}
                    return True
            except Exception as e:
                print(f"Error loading translations for {self.current_language}: {e}")
        
        # 如果加载失败，使用英文默认值
        self.translations = default_translations
        self.current_language = 'english'
        self.save_language_setting()
        return True
    
    def set_language(self, language_code):
        """设置当前语言"""
        if language_code != self.current_language:
            self.current_language = language_code
            if self.load_translations():
                self.save_language_setting()
                return True
        return False
    
    def get(self, key, default=None, **kwargs):
        """获取翻译文本，增强容错性"""
        # 先从当前翻译获取，如果没有则使用英文默认值，最后使用key
        text = self.translations.get(key, default or key)
        
        # 处理格式化错误
        try:
            if kwargs:
                return text.format(** kwargs)
            return text
        except (KeyError, ValueError) as e:
            print(f"Error formatting translation for key '{key}': {e}")
            # 返回未格式化的文本作为后备
            return text
    
    def get_available_languages(self):
        """获取可用的语言列表"""
        languages = []
        for file in self.languages_dir.iterdir():
            if file.suffix == '.json' and file.stem != '':
                lang_name = file.stem
                # 尝试获取语言的显示名称
                try:
                    with open(file, 'r', encoding='utf-8') as f:
                        lang_data = json.load(f)
                        # 使用配置文件中的语言名称，如果没有则使用文件名
                        display_name = lang_data.get('language_name', lang_name.capitalize())
                except:
                    display_name = lang_name.capitalize()
                
                # 特殊处理已知语言
                if lang_name == 'english':
                    display_name = 'English'
                elif lang_name == 'chinese':
                    display_name = '简体中文'
                    
                languages.append((lang_name, display_name))
        
        # 按显示名称排序
        languages.sort(key=lambda x: x[1])
        return languages

class ImageUtils:
    """图片处理工具类，用于处理封面图片尺寸"""
    @staticmethod
    def get_scaled_dimensions(width, height, max_size=213):
        """计算按比例缩放后的尺寸，确保最长边不超过max_size"""
        if width > height:
            ratio = max_size / width
        else:
            ratio = max_size / height
            
        new_width = int(width * ratio)
        new_height = int(height * ratio)
        
        return new_width, new_height

class PyDOSBox(Gtk.Application):
    def __init__(self):
        super().__init__(application_id='com.example.PyDOSBox')
        self.config_dir = Path.home() / '.pydosbox'
        self.gameconf_dir = self.config_dir / 'gameconf'
        self.covers_dir = self.config_dir / 'covers'
        self.games_dir = Path.home() / 'dosgames'
        self.games = []
        self.view_mode = 'list'
        self.dosbox_path = self.find_dosbox()
        self.show_hidden_games = False
        
        # 初始化翻译管理器
        self.translator = TranslationManager(self)
        
        # 确保所有必要目录存在
        self.config_dir.mkdir(parents=True, exist_ok=True)
        self.gameconf_dir.mkdir(parents=True, exist_ok=True)
        self.covers_dir.mkdir(parents=True, exist_ok=True)
        
        # 加载配置
        self.load_config()
        # 加载游戏列表
        self.load_games()

    def do_activate(self):
        # 创建主窗口
        self.main_window = MainWindow(application=self)
        self.main_window.show_all()

    def find_dosbox(self):
        """查找系统中的DOSBox可执行文件"""
        possible_paths = [
            '/usr/bin/dosbox',
            '/usr/local/bin/dosbox',
            '/opt/homebrew/bin/dosbox',
            'C:\\Program Files (x86)\\DOSBox-0.74-3\\dosbox.exe'
        ]
        
        for path in possible_paths:
            if os.path.exists(path) and os.access(path, os.X_OK):
                return path
        
        # 如果找不到，尝试通过which命令
        try:
            result = subprocess.run(['which', 'dosbox'], capture_output=True, text=True)
            if result.returncode == 0:
                return result.stdout.strip()
        except:
            pass
            
        return None

    def load_config(self):
        """加载应用配置"""
        config_file = self.config_dir / 'config.json'
        if config_file.exists():
            try:
                with open(config_file, 'r') as f:
                    config = json.load(f)
                    if 'games_dir' in config:
                        self.games_dir = Path(config['games_dir'])
                    if 'show_hidden_games' in config:
                        self.show_hidden_games = config['show_hidden_games']
                    if 'default_view' in config and config['default_view'] in ['list', 'grid']:
                        self.view_mode = config['default_view']
            except Exception as e:
                print(f"Error loading config: {e}")

    def save_config(self):
        """保存应用配置"""
        config_file = self.config_dir / 'config.json'
        try:
            with open(config_file, 'w') as f:
                json.dump({
                    'games_dir': str(self.games_dir),
                    'show_hidden_games': self.show_hidden_games,
                    'language': self.translator.current_language,
                    'default_view': self.view_mode
                }, f, indent=2)
        except Exception as e:
            print(f"Error saving config: {e}")

    def get_directory_size(self, path):
        """计算目录的总大小（MB）"""
        try:
            total_size = 0
            for dirpath, _, filenames in os.walk(path):
                for f in filenames:
                    fp = os.path.join(dirpath, f)
                    if not os.path.islink(fp):
                        total_size += os.path.getsize(fp)
            
            return round(total_size / (1024 * 1024), 2)
        except Exception as e:
            print(f"Error calculating size for {path}: {e}")
            return 0

    def calculate_total_games_size(self):
        """计算所有游戏占用的总空间（MB）"""
        total_size = 0
        for game in self.games:
            if not self.show_hidden_games and game.get('hidden', False):
                continue
                
            total_size += self.get_directory_size(game['path'])
        return round(total_size, 2)

    def load_games(self):
        """从游戏目录加载游戏列表"""
        self.games = []
        
        # 加载游戏元数据
        metadata_file = self.config_dir / 'games_metadata.json'
        metadata = {}
        if metadata_file.exists():
            try:
                with open(metadata_file, 'r') as f:
                    metadata = json.load(f)
            except Exception as e:
                print(f"Error loading games metadata: {e}")
        
        # 处理手动添加的游戏
        for game_id, game_info in metadata.items():
            if 'manual' in game_info and game_info['manual']:
                game_path = Path(game_info['path'])
                if game_path.exists() and game_path.is_dir():
                    default_conf = f"{game_id}_dosbox.conf"
                    game_size = self.get_directory_size(str(game_path))
                    
                    game = {
                        'id': game_id,
                        'name': game_info.get('name', game_id),
                        'path': game_info['path'],
                        'cover': game_info.get('cover', ''),
                        'conf': game_info.get('conf', default_conf),
                        'manual': True,
                        'hidden': game_info.get('hidden', False),
                        'size': game_size
                    }
                    
                    self.validate_cover_path(game)
                    conf_path = self.gameconf_dir / game['conf']
                    if not conf_path.exists():
                        self.create_default_config(game)
                        
                    self.games.append(game)
        
        # 扫描默认游戏目录中的游戏
        if self.games_dir.exists() and self.games_dir.is_dir():
            for item in self.games_dir.iterdir():
                if item.is_dir():
                    game_id = item.name
                    if game_id in metadata and 'manual' in metadata[game_id] and metadata[game_id]['manual']:
                        continue
                        
                    game_info = metadata.get(game_id, {})
                    default_conf = f"{game_id}_dosbox.conf"
                    game_size = self.get_directory_size(str(item))
                    
                    game = {
                        'id': game_id,
                        'name': game_info.get('name', item.name),
                        'path': str(item),
                        'cover': game_info.get('cover', ''),
                        'conf': game_info.get('conf', default_conf),
                        'manual': False,
                        'hidden': game_info.get('hidden', False),
                        'size': game_size
                    }
                    
                    self.validate_cover_path(game)
                    conf_path = self.gameconf_dir / game['conf']
                    if not conf_path.exists():
                        self.create_default_config(game)
                        
                    self.games.append(game)
        
        # 按名称排序
        self.games.sort(key=lambda x: x['name'].lower())

    def validate_cover_path(self, game):
        """验证封面路径，如果不在covers目录则更新路径"""
        if not game['cover']:
            return
            
        cover_path = Path(game['cover'])
        if not cover_path.exists():
            game['cover'] = ''
            return
            
        if cover_path.parent == self.covers_dir:
            return
            
        target_cover = self.covers_dir / cover_path.name
        if target_cover.exists():
            game['cover'] = str(target_cover)
        else:
            game['cover'] = ''

    def import_cover_image(self, game_id, source_path):
        """将封面图片导入到covers目录并返回新路径"""
        if not source_path or not os.path.exists(source_path):
            return ""
            
        try:
            ext = os.path.splitext(source_path)[1].lower()
            target_filename = f"{game_id}{ext}"
            target_path = self.covers_dir / target_filename
            
            shutil.copy2(source_path, target_path)
            
            with Image.open(target_path) as img:
                width, height = img.size
                if width > 213 or height > 213:
                    new_width, new_height = ImageUtils.get_scaled_dimensions(width, height, 213)
                    resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
                    resized_img.save(target_path)
            
            return str(target_path)
        except Exception as e:
            print(f"Error importing cover image: {e}")
            return ""

    def remove_unused_covers(self):
        """移除covers目录中未被任何游戏使用的图片"""
        used_covers = set()
        for game in self.games:
            if game['cover'] and os.path.exists(game['cover']):
                used_covers.add(os.path.basename(game['cover']))
        
        for cover_file in self.covers_dir.iterdir():
            if cover_file.is_file() and cover_file.name not in used_covers:
                try:
                    cover_file.unlink()
                    print(f"Removed unused cover: {cover_file.name}")
                except Exception as e:
                    print(f"Error removing unused cover {cover_file.name}: {e}")

    def create_default_config(self, game):
        """为游戏创建默认配置文件"""
        try:
            conf_path = self.gameconf_dir / game['conf']
            with open(conf_path, 'w') as f:
                f.write("[autoexec]\n")
                f.write(f"mount c {game['path']}\n")
                f.write("c:\n")
            return True
        except Exception as e:
            print(f"Error creating default config for {game['name']}: {e}")
            return False

    def save_game_metadata(self):
        """保存游戏元数据"""
        metadata_file = self.config_dir / 'games_metadata.json'
        metadata = {}
        
        for game in self.games:
            metadata[game['id']] = {
                'name': game['name'],
                'path': game['path'],
                'cover': game['cover'],
                'conf': game['conf'],
                'manual': game.get('manual', False),
                'hidden': game.get('hidden', False)
            }
            
        try:
            with open(metadata_file, 'w') as f:
                json.dump(metadata, f, indent=2)
        except Exception as e:
            print(f"Error saving games metadata: {e}")

    def update_game_info(self, game_id, new_info):
        """更新游戏信息"""
        for game in self.games:
            if game['id'] == game_id:
                if 'cover' in new_info and new_info['cover']:
                    if new_info['cover'] != game['cover']:
                        new_cover_path = self.import_cover_image(game_id, new_info['cover'])
                        new_info['cover'] = new_cover_path
                
                if 'conf' in new_info and new_info['conf'] != game['conf']:
                    old_path = self.gameconf_dir / game['conf']
                    new_path = self.gameconf_dir / new_info['conf']
                    if old_path.exists() and not new_path.exists():
                        try:
                            old_path.rename(new_path)
                        except Exception as e:
                            print(f"Error renaming config file: {e}")
                            return
                
                if 'path' in new_info and new_info['path'] != game['path']:
                    new_info['size'] = self.get_directory_size(new_info['path'])
                
                game.update(new_info)
                self.save_game_metadata()
                self.remove_unused_covers()
                self.main_window.update_games_list()
                break

    def add_manual_game(self, game_info):
        """手动添加一个游戏"""
        game_id = game_info['id']
        counter = 1
        while any(g['id'] == game_id for g in self.games):
            game_id = f"{game_info['id']}_{counter}"
            counter += 1
            
        cover_path = ""
        if 'cover' in game_info and game_info['cover']:
            cover_path = self.import_cover_image(game_id, game_info['cover'])
        
        game_size = self.get_directory_size(game_info['path'])
            
        default_conf = f"{game_id}_dosbox.conf"
        
        game = {
            'id': game_id,
            'name': game_info['name'],
            'path': game_info['path'],
            'cover': cover_path,
            'conf': game_info.get('conf', default_conf),
            'manual': True,
            'hidden': False,
            'size': game_size
        }
        
        self.create_default_config(game)
        
        self.games.append(game)
        self.save_game_metadata()
        self.main_window.update_games_list()
        return True

    def toggle_game_hidden(self, game_id):
        """切换游戏的隐藏状态"""
        for game in self.games:
            if game['id'] == game_id:
                game['hidden'] = not game['hidden']
                self.save_game_metadata()
                self.main_window.update_games_list()
                break

    def launch_game(self, game_id):
        """启动指定游戏"""
        for game in self.games:
            if game['id'] == game_id:
                if not self.dosbox_path:
                    self.show_error_dialog(
                        self.translator.get("dosbox_not_found"), 
                        self.translator.get("dosbox_not_found_msg")
                    )
                    return
                    
                conf_path = self.gameconf_dir / game['conf']
                if not conf_path.exists():
                    if not self.create_default_config(game):
                        self.show_error_dialog(
                            self.translator.get("error"), 
                            self.translator.get("could_not_create_config")
                        )
                        return
                
                try:
                    subprocess.Popen([
                        self.dosbox_path,
                        f"-conf", str(conf_path)
                    ])
                except Exception as e:
                    self.show_error_dialog(
                        self.translator.get("error_launching_game"), 
                        str(e)
                    )
                break

    def edit_config_file(self, game_id):
        """编辑游戏配置文件"""
        for game in self.games:
            if game['id'] == game_id:
                conf_path = self.gameconf_dir / game['conf']
                if not conf_path.exists():
                    if not self.create_default_config(game):
                        self.show_error_dialog(
                            self.translator.get("error"), 
                            self.translator.get("could_not_create_config")
                        )
                        return
                
                try:
                    subprocess.Popen(['xdg-open', str(conf_path)])
                except Exception as e:
                    self.show_error_dialog(
                        self.translator.get("error_opening_editor"), 
                        str(e)
                    )
                break

    def show_error_dialog(self, title, message):
        """显示错误对话框"""
        dialog = Gtk.MessageDialog(
            parent=self.main_window,
            flags=0,
            message_type=Gtk.MessageType.ERROR,
            buttons=Gtk.ButtonsType.OK,
            text=title
        )
        dialog.format_secondary_text(message)
        dialog.run()
        dialog.destroy()

    def change_language(self, language_code):
        """更改应用语言"""
        if self.translator.set_language(language_code):
            self.save_config()
            if hasattr(self, 'main_window'):
                self.main_window.destroy()
            self.main_window = MainWindow(application=self)
            self.main_window.show_all()
            return True
        return False

class MainWindow(Gtk.ApplicationWindow):
    def __init__(self, application):
        super().__init__(application=application, title=application.translator.get("app_title"))
        self.set_default_size(1000, 600)
        
        self.app = application
        self.trans = application.translator
        
        # 创建UI
        self.create_ui()
        
        # 初始化状态栏显示
        self.update_status_bar()
        
    def create_ui(self):
        """创建用户界面"""
        main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.add(main_box)
        
        # 设置窗口的标题栏
        self.setup_title_bar()
        
        # 创建工具栏
        tool_bar = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6, margin=6)
        tool_bar.set_homogeneous(False)
        main_box.pack_start(tool_bar, False, False, 0)
        
        # 添加游戏按钮
        add_game_btn = Gtk.Button(label=self.trans.get("add_game"))
        add_game_btn.set_image(Gtk.Image.new_from_icon_name("list-add-symbolic", Gtk.IconSize.BUTTON))
        add_game_btn.set_always_show_image(True)
        add_game_btn.connect("clicked", self.on_add_game_clicked)
        tool_bar.pack_start(add_game_btn, False, False, 0)
        
        # 分隔符
        separator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL)
        tool_bar.pack_start(separator, False, False, 6)
        
        # 视图切换按钮
        self.list_view_btn = Gtk.ToggleButton(label=self.trans.get("list_view"))
        self.list_view_btn.set_active(self.app.view_mode == 'list')
        self.list_view_btn.connect("toggled", self.on_view_mode_changed, "list")
        tool_bar.pack_start(self.list_view_btn, False, False, 0)
        
        self.grid_view_btn = Gtk.ToggleButton(label=self.trans.get("grid_view"))
        self.grid_view_btn.set_active(self.app.view_mode == 'grid')
        self.grid_view_btn.connect("toggled", self.on_view_mode_changed, "grid")
        tool_bar.pack_start(self.grid_view_btn, False, False, 0)
        
        # 分隔符
        separator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL)
        tool_bar.pack_start(separator, False, False, 6)
        
        # 刷新按钮
        refresh_btn = Gtk.Button(label=self.trans.get("refresh"))
        refresh_btn.connect("clicked", self.on_refresh_clicked)
        tool_bar.pack_start(refresh_btn, False, False, 0)
        
        # 游戏显示区域
        scrolled_window = Gtk.ScrolledWindow()
        scrolled_window.set_hexpand(True)
        scrolled_window.set_vexpand(True)
        main_box.pack_start(scrolled_window, True, True, 0)
        
        # 列表视图
        self.list_store = Gtk.ListStore(str, str, str, str, str)
        self.tree_view = Gtk.TreeView(model=self.list_store)
        self.tree_view.set_headers_visible(True)
        
        # 游戏名称列
        name_renderer = Gtk.CellRendererText()
        name_column = Gtk.TreeViewColumn(self.trans.get("name"), name_renderer, text=1)
        name_column.set_expand(True)
        self.tree_view.append_column(name_column)
        
        # 游戏大小列
        size_renderer = Gtk.CellRendererText()
        size_column = Gtk.TreeViewColumn(self.trans.get("game_size"), size_renderer, text=2)
        size_column.set_min_width(100)
        self.tree_view.append_column(size_column)
        
        # 编辑按钮列
        edit_renderer = Gtk.CellRendererText()
        edit_renderer.set_property("text", "✎")
        edit_renderer.set_property("editable", False)
        edit_renderer.set_property("xalign", 0.5)
        edit_column = Gtk.TreeViewColumn(self.trans.get("edit"), edit_renderer)
        edit_column.set_min_width(50)
        self.tree_view.append_column(edit_column)
        
        # 配置按钮列
        config_renderer = Gtk.CellRendererText()
        config_renderer.set_property("text", "⚙")
        config_renderer.set_property("editable", False)
        config_renderer.set_property("xalign", 0.5)
        config_column = Gtk.TreeViewColumn(self.trans.get("edit_config"), config_renderer)
        config_column.set_min_width(50)
        self.tree_view.append_column(config_column)
        
        # 工具提示处理
        self.tree_view.connect("query-tooltip", self.on_tree_view_query_tooltip)
        
        # 双击事件
        self.tree_view.connect("row-activated", self.on_tree_row_activated)
        # 右键菜单事件
        self.tree_view.connect("button-press-event", self.on_tree_right_click)
        
        # 网格视图
        self.grid_box = Gtk.FlowBox()
        self.grid_box.set_valign(Gtk.Align.START)
        self.grid_box.set_max_children_per_line(6)
        self.grid_box.set_selection_mode(Gtk.SelectionMode.NONE)
        self.grid_box.connect("child-activated", self.on_grid_game_activated)
        self.grid_box.connect("button-press-event", self.on_grid_right_click)
        
        # 初始视图
        self.current_view = self.tree_view if self.app.view_mode == 'list' else self.grid_box
        scrolled_window.add(self.current_view)
        
        # 状态栏
        self.status_bar = Gtk.Statusbar()
        self.status_bar.set_margin_start(6)
        self.status_bar.set_margin_end(6)
        self.status_bar.set_margin_top(3)
        self.status_bar.set_margin_bottom(3)
        main_box.pack_start(self.status_bar, False, False, 0)
        
        # 初始化游戏列表
        self.update_games_list()

    def on_tree_view_query_tooltip(self, widget, x, y, keyboard_mode, tooltip):
        """处理树视图的工具提示查询事件"""
        path, column, cell_x, cell_y = widget.get_path_at_pos(x, y)
        if path and column:
            col_index = widget.get_columns().index(column)
            tree_iter = self.list_store.get_iter(path)
            game_id = self.list_store.get_value(tree_iter, 0)
            
            if col_index == 2:
                tooltip.set_text(self.trans.get("edit"))
            elif col_index == 3:
                tooltip.set_text(self.trans.get("edit_config"))
            else:
                return False
                
            return True
        return False

    def on_tree_row_activated(self, tree_view, path, column):
        """列表视图中游戏被激活（双击）"""
        col_index = tree_view.get_columns().index(column)
        game_id = self.get_game_id_from_path(path)
        
        if col_index == 0:
            self.app.launch_game(game_id)
        elif col_index == 2:
            self.on_edit_game(game_id)
        elif col_index == 3:
            self.on_edit_config(game_id)

    def get_game_id_from_path(self, path):
        """从TreeView路径获取游戏ID"""
        tree_iter = self.list_store.get_iter(path)
        return self.list_store.get_value(tree_iter, 0)

    def on_tree_right_click(self, widget, event):
        """树视图右键菜单"""
        if event.button != 3:
            return False
            
        try:
            path, _, _, _ = self.tree_view.get_path_at_pos(int(event.x), int(event.y))
            if path:
                game_id = self.get_game_id_from_path(path)
                self.show_game_context_menu(event, game_id)
                return True
        except:
            pass
        return False

    def update_status_bar(self):
        """更新状态栏显示游戏总数"""
        context_id = self.status_bar.get_context_id("game_count")
        self.status_bar.remove_all(context_id)
        
        try:
            total = len(self.app.games)
            status_text = self.trans.get("total_games").format(count=total)
            self.status_bar.push(context_id, status_text)
        except Exception as e:
            self.status_bar.push(context_id, f"Total games: {len(self.app.games)}")
            print(f"Status bar error: {e}")

    def create_grid_card(self, game):
        """创建网格视图中的游戏卡片"""
        card = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=4, margin=4)
        card.set_size_request(147, 240)
        
        if game.get('hidden', False):
            card.set_opacity(0.6)
        
        cover_frame = Gtk.AspectFrame(ratio=3/4, obey_child=False)
        cover_frame.set_shadow_type(Gtk.ShadowType.NONE)
        
        cover_align = Gtk.Alignment(xalign=0.5, yalign=0.5, xscale=0, yscale=0)
        
        if game['cover'] and os.path.exists(game['cover']):
            try:
                with Image.open(game['cover']) as img:
                    width, height = img.size
                    new_width, new_height = ImageUtils.get_scaled_dimensions(width, height, 213)
                    
                    cover_img = Gtk.Image.new_from_file(game['cover'])
                    cover_img.set_pixel_size(max(new_width, new_height))
                    cover_img.set_size_request(new_width, new_height)
            except:
                cover_img = Gtk.Image.new_from_icon_name("image-missing-symbolic", Gtk.IconSize.DIALOG)
                cover_img.set_pixel_size(213)
        else:
            cover_img = Gtk.Image.new_from_icon_name("image-missing-symbolic", Gtk.IconSize.DIALOG)
            cover_img.set_pixel_size(213)
        
        cover_align.add(cover_img)
        cover_frame.add(cover_align)
        card.pack_start(cover_frame, True, True, 0)
        
        if game.get('hidden', False):
            name_label = Gtk.Label(label=f"[{game['name']}]", xalign=0.5)
        else:
            name_label = Gtk.Label(label=game['name'], xalign=0.5)
        name_label.set_max_width_chars(15)
        name_label.set_ellipsize(Pango.EllipsizeMode.END)
        card.pack_start(name_label, False, False, 0)
        
        size_label = Gtk.Label(label=f"{game['size']} MB", xalign=0.5)
        size_label.set_opacity(0.7)
        card.pack_start(size_label, False, False, 0)
        
        card.game_id = game['id']
        
        return card

    def on_view_mode_changed(self, button, mode):
        """切换视图模式"""
        if button.get_active():
            self.app.view_mode = mode
            scrolled_window = self.current_view.get_parent()
            
            if mode == 'list':
                self.current_view = self.tree_view
                self.grid_view_btn.set_active(False)
            else:
                self.current_view = self.grid_box
                self.list_view_btn.set_active(False)
                
            scrolled_window.remove(scrolled_window.get_child())
            scrolled_window.add(self.current_view)
            self.update_games_list()
            self.app.save_config()

    def on_refresh_clicked(self, button):
        """刷新游戏列表"""
        self.app.load_games()
        self.update_games_list()

    def on_grid_game_activated(self, flow_box, child):
        """网格视图中游戏被激活（双击）"""
        self.app.launch_game(child.get_child().game_id)

    def on_edit_game(self, game_id):
        """编辑游戏信息"""
        game = next((g for g in self.app.games if g['id'] == game_id), None)
        if game:
            dialog = GameEditDialog(self, game)
            dialog.run()
            dialog.destroy()

    def on_edit_config(self, game_id):
        """编辑游戏配置文件"""
        self.app.edit_config_file(game_id)

    def on_add_game_clicked(self, button):
        """添加新游戏"""
        dialog = AddGameDialog(self)
        dialog.run()
        dialog.destroy()

    def on_settings_clicked(self, menu_item):
        """打开设置对话框"""
        dialog = SettingsDialog(self)
        dialog.run()
        dialog.destroy()

    def on_about_clicked(self, menu_item):
        """打开关于对话框"""
        dialog = AboutDialog(self)
        dialog.run()
        dialog.destroy()

    def on_grid_right_click(self, widget, event):
        """网格视图右键菜单"""
        if event.button != 3:
            return False
            
        child = self.grid_box.get_child_at_pos(int(event.x), int(event.y))
        if child:
            game_id = child.get_child().game_id
            self.show_game_context_menu(event, game_id)
            return True
        return False

    def show_game_context_menu(self, event, game_id):
        """显示游戏右键菜单"""
        menu = Gtk.Menu()
        
        game = next((g for g in self.app.games if g['id'] == game_id), None)
        if not game:
            return
            
        if game.get('hidden', False):
            hide_item = Gtk.MenuItem(label=self.trans.get("unhide_game"))
        else:
            hide_item = Gtk.MenuItem(label=self.trans.get("hide_game"))
        hide_item.connect("activate", lambda w: self.app.toggle_game_hidden(game_id))
        menu.append(hide_item)
        
        separator = Gtk.SeparatorMenuItem()
        menu.append(separator)
        
        edit_item = Gtk.MenuItem(label=self.trans.get("edit_game"))
        edit_item.connect("activate", lambda w: self.on_edit_game(game_id))
        menu.append(edit_item)
        
        edit_conf_item = Gtk.MenuItem(label=self.trans.get("edit_config"))
        edit_conf_item.connect("activate", lambda w: self.on_edit_config(game_id))
        menu.append(edit_conf_item)
        
        launch_item = Gtk.MenuItem(label=self.trans.get("launch_game"))
        launch_item.connect("activate", lambda w: self.app.launch_game(game_id))
        menu.append(launch_item)
        
        menu.show_all()
        menu.popup_at_pointer(event)

    def update_games_list(self):
        """更新游戏列表显示并刷新状态栏"""
        if self.app.view_mode == 'list':
            self.list_store.clear()
        else:
            for child in self.grid_box.get_children():
                self.grid_box.remove(child)
        
        filtered_games = self.app.games
        if not self.app.show_hidden_games:
            filtered_games = [g for g in self.app.games if not g.get('hidden', False)]
        
        if self.app.view_mode == 'list':
            for game in filtered_games:
                if game.get('hidden', False):
                    display_name = f"[{game['name']}]"
                else:
                    display_name = game['name']
                
                self.list_store.append([
                    game['id'], 
                    display_name,
                    f"{game['size']}",
                    self.trans.get("edit"),
                    self.trans.get("edit_config")
                ])
        else:
            for game in filtered_games:
                card = self.create_grid_card(game)
                self.grid_box.add(card)
        
        self.current_view.show_all()
        self.update_status_bar()

    def setup_title_bar(self):
        """设置窗口的标题栏"""
        header_bar = Gtk.HeaderBar()
        header_bar.set_show_close_button(True)
        header_bar.set_title(self.trans.get("app_title"))
        
        menu_btn = Gtk.MenuButton()
        menu_icon = Gtk.Image.new_from_icon_name("open-menu-symbolic", Gtk.IconSize.BUTTON)
        menu_btn.add(menu_icon)
        
        menu = Gtk.Menu()
        
        settings_item = Gtk.MenuItem(label=self.trans.get("settings"))
        settings_item.connect("activate", self.on_settings_clicked)
        menu.append(settings_item)
        
        separator = Gtk.SeparatorMenuItem()
        menu.append(separator)
        
        about_item = Gtk.MenuItem(label=self.trans.get("about"))
        about_item.connect("activate", self.on_about_clicked)
        menu.append(about_item)
        
        menu.show_all()
        menu_btn.set_popup(menu)
        header_bar.pack_end(menu_btn)
        
        self.set_titlebar(header_bar)

class AddGameDialog(Gtk.Dialog):
    def __init__(self, parent):
        self.parent = parent
        self.trans = parent.app.translator
        super().__init__(
            transient_for=parent, 
            title=self.trans.get("add_new_game")
        )
        self.set_default_size(600, 400)
        
        self.add_button(self.trans.get("cancel"), Gtk.ResponseType.CANCEL)
        self.add_button(self.trans.get("add"), Gtk.ResponseType.OK)
        self.set_default_response(Gtk.ResponseType.OK)
        
        self.connect("response", self.on_response)
        
        content_area = self.get_content_area()
        content_area.set_spacing(12)
        content_area.set_margin_start(12)
        content_area.set_margin_end(12)
        content_area.set_margin_top(12)
        content_area.set_margin_bottom(12)
        
        # 游戏ID
        id_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        id_label = Gtk.Label(label=self.trans.get("id_internal"), xalign=0, width_request=120)
        self.id_entry = Gtk.Entry()
        id_box.pack_start(id_label, False, False, 0)
        id_box.pack_start(self.id_entry, True, True, 0)
        content_area.pack_start(id_box, False, False, 0)
        
        # 游戏名称
        name_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        name_label = Gtk.Label(label=self.trans.get("name"), xalign=0, width_request=120)
        self.name_entry = Gtk.Entry()
        name_box.pack_start(name_label, False, False, 0)
        name_box.pack_start(self.name_entry, True, True, 0)
        content_area.pack_start(name_box, False, False, 0)
        
        # 游戏目录
        path_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        path_label = Gtk.Label(label=self.trans.get("game_directory"), xalign=0, width_request=120)
        self.path_entry = Gtk.Entry()
        path_box.pack_start(path_label, False, False, 0)
        path_box.pack_start(self.path_entry, True, True, 0)
        
        path_btn = Gtk.Button(label=self.trans.get("browse"))
        path_btn.connect("clicked", self.on_browse_path)
        path_box.pack_start(path_btn, False, False, 0)
        
        content_area.pack_start(path_box, False, False, 0)
        
        # 配置文件
        conf_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        conf_label = Gtk.Label(label=self.trans.get("config_file"), xalign=0, width_request=120)
        self.conf_entry = Gtk.Entry()
        conf_box.pack_start(conf_label, False, False, 0)
        conf_box.pack_start(self.conf_entry, True, True, 0)
        
        content_area.pack_start(conf_box, False, False, 0)
        
        # 路径提示
        paths_info = Gtk.Label(
            label=f"{self.trans.get('config_file')} {self.trans.get('stored_in')}: {parent.app.gameconf_dir}\n"
                  f"{self.trans.get('cover_image')} {self.trans.get('stored_in')}: {parent.app.covers_dir}", 
            xalign=0
        )
        paths_info.set_opacity(0.7)
        paths_info.set_margin_start(126)
        paths_info.set_line_wrap(True)
        content_area.pack_start(paths_info, False, False, 0)
        
        # 封面图片
        cover_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        cover_label = Gtk.Label(label=self.trans.get("cover_image"), xalign=0)
        
        cover_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        self.cover_entry = Gtk.Entry()
        self.cover_entry.set_hexpand(True)
        
        cover_btn = Gtk.Button(label=self.trans.get("browse"))
        cover_btn.connect("clicked", self.on_browse_cover)
        
        cover_hbox.pack_start(self.cover_entry, True, True, 0)
        cover_hbox.pack_start(cover_btn, False, False, 0)
        
        self.cover_preview = Gtk.Image()
        self.cover_preview.set_size_request(160, 213)
        self.cover_preview.set_from_icon_name("image-missing-symbolic", Gtk.IconSize.DIALOG)
        
        cover_box.pack_start(cover_label, False, False, 0)
        cover_box.pack_start(cover_hbox, False, False, 0)
        cover_box.pack_start(self.cover_preview, False, False, 0)
        
        content_area.pack_start(cover_box, False, False, 0)
        
        self.show_all()

    def on_browse_path(self, button):
        """浏览游戏目录"""
        dialog = Gtk.FileChooserDialog(
            title=self.trans.get("game_directory"),
            transient_for=self,
            action=Gtk.FileChooserAction.SELECT_FOLDER
        )
        dialog.add_buttons(
            self.trans.get("cancel"), Gtk.ResponseType.CANCEL,
            self.trans.get("select"), Gtk.ResponseType.OK
        )
        
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            self.path_entry.set_text(dialog.get_filename())
            if not self.id_entry.get_text():
                self.id_entry.set_text(os.path.basename(dialog.get_filename()))
            if not self.name_entry.get_text():
                self.name_entry.set_text(os.path.basename(dialog.get_filename()))
            if not self.conf_entry.get_text() and self.id_entry.get_text():
                self.conf_entry.set_text(f"{self.id_entry.get_text()}_dosbox.conf")
        dialog.destroy()

    def on_browse_cover(self, button):
        """浏览封面图片"""
        dialog = Gtk.FileChooserDialog(
            title=self.trans.get("cover_image"),
            transient_for=self,
            action=Gtk.FileChooserAction.OPEN
        )
        dialog.add_buttons(
            self.trans.get("cancel"), Gtk.ResponseType.CANCEL,
            self.trans.get("select"), Gtk.ResponseType.OK
        )
        
        filter_pixbuf = Gtk.FileFilter()
        filter_pixbuf.set_name(self.trans.get("image_files"))
        filter_pixbuf.add_mime_type("image/*")
        dialog.add_filter(filter_pixbuf)
        
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            cover_path = dialog.get_filename()
            self.cover_entry.set_text(cover_path)
            
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                cover_path, 
                width=160,
                height=213,
                preserve_aspect_ratio=True
            )
            self.cover_preview.set_from_pixbuf(pixbuf)
            
        dialog.destroy()

    def on_response(self, dialog, response_id):
        """处理对话框响应"""
        if response_id == Gtk.ResponseType.OK:
            game_id = self.id_entry.get_text().strip()
            name = self.name_entry.get_text().strip()
            path = self.path_entry.get_text().strip()
            
            if not game_id or not name or not path:
                self.parent.app.show_error_dialog(
                    self.trans.get("error"), 
                    self.trans.get("required_fields")
                )
                return
                
            if not os.path.exists(path) or not os.path.isdir(path):
                self.parent.app.show_error_dialog(
                    self.trans.get("error"), 
                    self.trans.get("invalid_directory")
                )
                return
                
            game_info = {
                'id': game_id,
                'name': name,
                'path': path,
                'cover': self.cover_entry.get_text().strip()
            }
            
            conf = self.conf_entry.get_text().strip()
            if conf:
                game_info['conf'] = conf
                
            self.parent.app.add_manual_game(game_info)
        
        self.destroy()

class GameEditDialog(Gtk.Dialog):
    def __init__(self, parent, game):
        self.parent = parent
        self.trans = parent.app.translator
        self.game = game
        
        super().__init__(
            transient_for=parent, 
            title=self.trans.get("edit_game_title", game_name=game['name'])
        )
        self.set_default_size(600, 400)
        
        self.add_button(self.trans.get("cancel"), Gtk.ResponseType.CANCEL)
        self.add_button(self.trans.get("save"), Gtk.ResponseType.OK)
        self.set_default_response(Gtk.ResponseType.OK)
        
        self.connect("response", self.on_response)
        
        content_area = self.get_content_area()
        content_area.set_spacing(12)
        content_area.set_margin_start(12)
        content_area.set_margin_end(12)
        content_area.set_margin_top(12)
        content_area.set_margin_bottom(12)
        
        # 游戏ID
        id_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        id_label = Gtk.Label(label=self.trans.get("id_internal"), xalign=0, width_request=120)
        self.id_entry = Gtk.Entry(text=game['id'])
        self.id_entry.set_sensitive(False)
        id_box.pack_start(id_label, False, False, 0)
        id_box.pack_start(self.id_entry, True, True, 0)
        content_area.pack_start(id_box, False, False, 0)
        
        # 游戏名称
        name_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        name_label = Gtk.Label(label=self.trans.get("name"), xalign=0, width_request=120)
        self.name_entry = Gtk.Entry(text=game['name'])
        name_box.pack_start(name_label, False, False, 0)
        name_box.pack_start(self.name_entry, True, True, 0)
        content_area.pack_start(name_box, False, False, 0)
        
        # 游戏目录
        path_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        path_label = Gtk.Label(label=self.trans.get("game_directory"), xalign=0, width_request=120)
        self.path_entry = Gtk.Entry(text=game['path'])
        path_box.pack_start(path_label, False, False, 0)
        path_box.pack_start(self.path_entry, True, True, 0)
        
        path_btn = Gtk.Button(label=self.trans.get("browse"))
        path_btn.connect("clicked", self.on_browse_path)
        path_box.pack_start(path_btn, False, False, 0)
        
        content_area.pack_start(path_box, False, False, 0)
        
        # 游戏大小
        size_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        size_label = Gtk.Label(label=self.trans.get("game_size"), xalign=0, width_request=120)
        game_size = game.get('size', 0)
        self.size_entry = Gtk.Entry(text=f"{game_size} MB")
        self.size_entry.set_sensitive(False)
        size_box.pack_start(size_label, False, False, 0)
        size_box.pack_start(self.size_entry, True, True, 0)
        content_area.pack_start(size_box, False, False, 0)
        
        # 配置文件
        conf_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        conf_label = Gtk.Label(label=self.trans.get("config_file"), xalign=0, width_request=120)
        self.conf_entry = Gtk.Entry(text=game['conf'])
        conf_box.pack_start(conf_label, False, False, 0)
        conf_box.pack_start(self.conf_entry, True, True, 0)
        
        edit_conf_btn = Gtk.Button(label=self.trans.get("edit"))
        edit_conf_btn.connect("clicked", self.on_edit_config)
        conf_box.pack_start(edit_conf_btn, False, False, 0)
        
        content_area.pack_start(conf_box, False, False, 0)
        
        # 路径提示
        conf_path = parent.app.gameconf_dir / game['conf']
        paths_info = Gtk.Label(
            label=f"{self.trans.get('config_file')} {self.trans.get('stored_in')}: {conf_path}\n"
                  f"{self.trans.get('cover_image')} {self.trans.get('stored_in')}: {parent.app.covers_dir}", 
            xalign=0
        )
        paths_info.set_opacity(0.7)
        paths_info.set_margin_start(126)
        paths_info.set_line_wrap(True)
        content_area.pack_start(paths_info, False, False, 0)
        
        # 隐藏游戏选项
        hidden_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        self.hidden_check = Gtk.CheckButton(label=self.trans.get("hide_this_game"))
        self.hidden_check.set_active(game.get('hidden', False))
        hidden_box.pack_start(self.hidden_check, False, False, 126)
        content_area.pack_start(hidden_box, False, False, 0)
        
        # 封面图片
        cover_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        cover_label = Gtk.Label(label=self.trans.get("cover_image"), xalign=0)
        
        cover_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        self.cover_entry = Gtk.Entry(text=game['cover'])
        self.cover_entry.set_hexpand(True)
        
        cover_btn = Gtk.Button(label=self.trans.get("browse"))
        cover_btn.connect("clicked", self.on_browse_cover)
        
        cover_hbox.pack_start(self.cover_entry, True, True, 0)
        cover_hbox.pack_start(cover_btn, False, False, 0)
        
        self.cover_preview = Gtk.Image()
        self.cover_preview.set_size_request(160, 213)
        if game['cover'] and os.path.exists(game['cover']):
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                game['cover'], 
                width=160,
                height=213,
                preserve_aspect_ratio=True
            )
            self.cover_preview.set_from_pixbuf(pixbuf)
        else:
            self.cover_preview.set_from_icon_name("image-missing-symbolic", Gtk.IconSize.DIALOG)
        
        cover_box.pack_start(cover_label, False, False, 0)
        cover_box.pack_start(cover_hbox, False, False, 0)
        cover_box.pack_start(self.cover_preview, False, False, 0)
        
        content_area.pack_start(cover_box, False, False, 0)
        
        self.show_all()

    def on_browse_path(self, button):
        """浏览游戏目录"""
        dialog = Gtk.FileChooserDialog(
            title=self.trans.get("game_directory"),
            transient_for=self,
            action=Gtk.FileChooserAction.SELECT_FOLDER
        )
        dialog.add_buttons(
            self.trans.get("cancel"), Gtk.ResponseType.CANCEL,
            self.trans.get("select"), Gtk.ResponseType.OK
        )
        
        current_path = self.path_entry.get_text()
        if current_path and os.path.exists(current_path):
            dialog.set_current_folder(current_path)
        
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            new_path = dialog.get_filename()
            self.path_entry.set_text(new_path)
            
            new_size = self.parent.app.get_directory_size(new_path)
            self.size_entry.set_text(f"{new_size} MB")
            
        dialog.destroy()

    def on_browse_cover(self, button):
        """浏览封面图片"""
        dialog = Gtk.FileChooserDialog(
            title=self.trans.get("cover_image"),
            transient_for=self,
            action=Gtk.FileChooserAction.OPEN
        )
        dialog.add_buttons(
            self.trans.get("cancel"), Gtk.ResponseType.CANCEL,
            self.trans.get("select"), Gtk.ResponseType.OK
        )
        
        filter_pixbuf = Gtk.FileFilter()
        filter_pixbuf.set_name(self.trans.get("image_files"))
        filter_pixbuf.add_mime_type("image/*")
        dialog.add_filter(filter_pixbuf)
        
        current_cover = self.cover_entry.get_text()
        if current_cover and os.path.exists(current_cover):
            dialog.set_filename(current_cover)
        
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            cover_path = dialog.get_filename()
            self.cover_entry.set_text(cover_path)
            
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                cover_path, 
                width=160,
                height=213,
                preserve_aspect_ratio=True
            )
            self.cover_preview.set_from_pixbuf(pixbuf)
            
        dialog.destroy()

    def on_edit_config(self, button=None):
        """编辑当前游戏的配置文件"""
        self.parent.app.edit_config_file(self.game['id'])

    def on_response(self, dialog, response_id):
        """处理对话框响应"""
        if response_id == Gtk.ResponseType.OK:
            name = self.name_entry.get_text().strip()
            path = self.path_entry.get_text().strip()
            
            if not name or not path:
                self.parent.app.show_error_dialog(
                    self.trans.get("error"), 
                    self.trans.get("required_fields")
                )
                return
                
            if not os.path.exists(path) or not os.path.isdir(path):
                self.parent.app.show_error_dialog(
                    self.trans.get("error"), 
                    self.trans.get("invalid_directory")
                )
                return
                
            new_info = {
                'name': name,
                'path': path,
                'cover': self.cover_entry.get_text().strip(),
                'conf': self.conf_entry.get_text().strip(),
                'hidden': self.hidden_check.get_active()
            }
            self.parent.app.update_game_info(self.game['id'], new_info)
        
        self.destroy()

class SettingsDialog(Gtk.Dialog):
    def __init__(self, parent):
        self.parent = parent
        self.trans = parent.app.translator
        
        super().__init__(
            transient_for=parent, 
            title=self.trans.get("settings_title")
        )
        self.set_default_size(500, 320)
        
        self.add_button(self.trans.get("cancel"), Gtk.ResponseType.CANCEL)
        self.add_button(self.trans.get("save"), Gtk.ResponseType.OK)
        self.set_default_response(Gtk.ResponseType.OK)
        
        self.connect("response", self.on_response)
        
        content_area = self.get_content_area()
        content_area.set_border_width(12)
        
        notebook = Gtk.Notebook()
        content_area.pack_start(notebook, True, True, 0)
        
        # 基本设置选项卡
        basic_tab = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
        basic_tab.set_border_width(12)
        
        # 游戏目录设置
        games_dir_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        
        dir_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        dir_label = Gtk.Label(label=self.trans.get("games_directory"), xalign=0)
        self.dir_entry = Gtk.Entry(text=str(parent.app.games_dir))
        self.dir_entry.set_hexpand(True)
        
        dir_btn = Gtk.Button(label=self.trans.get("browse"))
        dir_btn.connect("clicked", self.on_browse_dir)
        
        dir_hbox.pack_start(dir_label, False, False, 0)
        dir_hbox.pack_start(self.dir_entry, True, True, 0)
        dir_hbox.pack_start(dir_btn, False, False, 0)
        
        games_dir_box.pack_start(dir_hbox, False, False, 0)
        basic_tab.pack_start(games_dir_box, False, False, 0)
        
        # 目录信息
        dirs_info = Gtk.Label(
            label=f"{self.trans.get('config_file')} {self.trans.get('stored_in')}: {parent.app.gameconf_dir}\n"
                  f"{self.trans.get('cover_image')} {self.trans.get('stored_in')}: {parent.app.covers_dir}", 
            xalign=0
        )
        dirs_info.set_line_wrap(True)
        dirs_info.set_opacity(0.7)
        basic_tab.pack_start(dirs_info, False, False, 6)
        
        # DOSBox路径设置
        dosbox_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        
        dosbox_hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        dosbox_label = Gtk.Label(label=self.trans.get("dosbox_path"), xalign=0)
        self.dosbox_entry = Gtk.Entry(text=parent.app.dosbox_path or "")
        self.dosbox_entry.set_hexpand(True)
        
        dosbox_btn = Gtk.Button(label=self.trans.get("browse"))
        dosbox_btn.connect("clicked", self.on_browse_dosbox)
        
        dosbox_hbox.pack_start(dosbox_label, False, False, 0)
        dosbox_hbox.pack_start(self.dosbox_entry, True, True, 0)
        dosbox_hbox.pack_start(dosbox_btn, False, False, 0)
        
        dosbox_box.pack_start(dosbox_hbox, False, False, 0)
        basic_tab.pack_start(dosbox_box, False, False, 0)
        
        notebook.append_page(basic_tab, Gtk.Label(label=self.trans.get("basic_tab")))
        
        # 视图设置选项卡
        view_tab = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
        view_tab.set_border_width(12)
        
        # 显示隐藏游戏选项
        hidden_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        self.show_hidden_check = Gtk.CheckButton(label=self.trans.get("show_hidden_games"))
        self.show_hidden_check.set_active(parent.app.show_hidden_games)
        hidden_box.pack_start(self.show_hidden_check, False, False, 0)
        view_tab.pack_start(hidden_box, False, False, 0)
        
        # 分隔线
        separator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
        view_tab.pack_start(separator, False, False, 6)
        
        # 默认视图设置
        default_view_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        
        view_label = Gtk.Label(label=self.trans.get("default_view"), xalign=0)
        default_view_box.pack_start(view_label, False, False, 0)
        
        radio_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        radio_box.set_margin_start(12)
        
        self.list_radio = Gtk.RadioButton.new_with_label(None, self.trans.get("show_game_list"))
        radio_box.pack_start(self.list_radio, False, False, 0)
        
        self.grid_radio = Gtk.RadioButton.new_with_label_from_widget(
            self.list_radio, self.trans.get("show_game_grid")
        )
        radio_box.pack_start(self.grid_radio, False, False, 0)
        
        if parent.app.view_mode == 'list':
            self.list_radio.set_active(True)
        else:
            self.grid_radio.set_active(True)
        
        default_view_box.pack_start(radio_box, False, False, 0)
        view_tab.pack_start(default_view_box, False, False, 0)
        
        notebook.append_page(view_tab, Gtk.Label(label=self.trans.get("view_tab")))
        
        # 统计设置选项卡
        stats_tab = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
        stats_tab.set_border_width(12)
        
        # 计算统计数据并确保显示逻辑正确
        try:
            # 获取所有游戏
            all_games = parent.app.games
            # 计算可见游戏（排除隐藏的）
            visible_games = [g for g in all_games if not g.get('hidden', False)]
            visible_count = len(visible_games)
            total_count = len(all_games)
            
            # 计算总空间（只计算可见游戏）
            total_size = 0.0
            for game in visible_games:
                # 确保每个游戏都有size属性
                if 'size' not in game:
                    game['size'] = parent.app.get_directory_size(game['path'])
                total_size += game['size']
            total_size = round(total_size, 2)
            
            # 游戏总数
            total_games_text = self.trans.get("total_games_stats", 
                                           default=f"Total games: {visible_count}",
                                           count=visible_count)
            total_games_label = Gtk.Label(label=total_games_text, xalign=0)
            total_games_label.set_margin_bottom(6)
            stats_tab.pack_start(total_games_label, False, False, 0)
            
            # 总占用空间
            total_space_text = self.trans.get("total_space_used",
                                           default=f"Total space used: {total_size} MB",
                                           size=total_size)
            total_space_label = Gtk.Label(label=total_space_text, xalign=0)
            stats_tab.pack_start(total_space_label, False, False, 0)
            
            # 隐藏游戏提示 - 使用新的翻译键
            if total_count > visible_count:
                hidden_note = Gtk.Label(
                    label=f"({self.trans.get('total_games_stats', count=total_count)} {self.trans.get('including_hidden_games')})",
                    xalign=0
                )
                hidden_note.set_opacity(0.7)
                hidden_note.set_margin_top(6)
                stats_tab.pack_start(hidden_note, False, False, 0)
                
        except Exception as e:
            # 出错时显示原始数据，不依赖翻译
            error_label = Gtk.Label(label=f"Error loading statistics: {str(e)}", xalign=0)
            error_label.set_property("wrap", True)
            stats_tab.pack_start(error_label, False, False, 0)
            
            # 显示原始统计数据作为后备
            count_label = Gtk.Label(label=f"Total games: {len(parent.app.games)}", xalign=0)
            stats_tab.pack_start(count_label, False, False, 6)
            
            size_label = Gtk.Label(label=f"Total space: {parent.app.calculate_total_games_size()} MB", xalign=0)
            stats_tab.pack_start(size_label, False, False, 0)
        
        notebook.append_page(stats_tab, Gtk.Label(label=self.trans.get("statistics_tab")))
        
        # 语言设置选项卡
        language_tab = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
        language_tab.set_border_width(12)
        
        # 语言选择
        lang_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
        lang_label = Gtk.Label(label=self.trans.get("select_language"), xalign=0, width_request=120)
        
        self.lang_combo = Gtk.ComboBoxText()
        self.lang_combo.set_hexpand(True)
        
        languages = parent.app.translator.get_available_languages()
        current_lang = parent.app.translator.current_language
        selected_index = 0
        
        for i, (lang_code, display_name) in enumerate(languages):
            self.lang_combo.append(lang_code, display_name)
            if lang_code == current_lang:
                selected_index = i
        
        self.lang_combo.set_active(selected_index)
        
        lang_box.pack_start(lang_label, False, False, 0)
        lang_box.pack_start(self.lang_combo, True, True, 0)
        language_tab.pack_start(lang_box, False, False, 0)
        
        # 语言文件位置信息
        lang_info = Gtk.Label(
            label=f"{self.trans.get('language_files_stored_in')}: {parent.app.translator.languages_dir}", 
            xalign=0
        )
        lang_info.set_line_wrap(True)
        lang_info.set_opacity(0.7)
        language_tab.pack_start(lang_info, False, False, 12)
        
        notebook.append_page(language_tab, Gtk.Label(label=self.trans.get("language_tab")))
        
        self.show_all()

    def on_browse_dir(self, button):
        """浏览游戏目录"""
        dialog = Gtk.FileChooserDialog(
            title=self.trans.get("games_directory"),
            transient_for=self,
            action=Gtk.FileChooserAction.SELECT_FOLDER
        )
        dialog.add_buttons(
            self.trans.get("cancel"), Gtk.ResponseType.CANCEL,
            self.trans.get("select"), Gtk.ResponseType.OK
        )
        
        if self.parent.app.games_dir.exists():
            dialog.set_current_folder(str(self.parent.app.games_dir))
        
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            self.dir_entry.set_text(dialog.get_filename())
        dialog.destroy()

    def on_browse_dosbox(self, button):
        """浏览DOSBox可执行文件"""
        dialog = Gtk.FileChooserDialog(
            title=self.trans.get("dosbox_path"),
            transient_for=self,
            action=Gtk.FileChooserAction.OPEN
        )
        dialog.add_buttons(
            self.trans.get("cancel"), Gtk.ResponseType.CANCEL,
            self.trans.get("select"), Gtk.ResponseType.OK
        )
        
        if self.parent.app.dosbox_path and os.path.exists(self.parent.app.dosbox_path):
            dialog.set_filename(self.parent.app.dosbox_path)
        
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            self.dosbox_entry.set_text(dialog.get_filename())
        dialog.destroy()

    def on_response(self, dialog, response_id):
        """处理对话框响应"""
        if response_id == Gtk.ResponseType.OK:
            # 更新显示隐藏游戏设置
            show_hidden = self.show_hidden_check.get_active()
            if show_hidden != self.parent.app.show_hidden_games:
                self.parent.app.show_hidden_games = show_hidden
                self.parent.app.save_config()
                self.parent.update_games_list()
            
            # 保存游戏目录设置
            new_games_dir = Path(self.dir_entry.get_text())
            if new_games_dir != self.parent.app.games_dir:
                self.parent.app.games_dir = new_games_dir
                self.parent.app.save_config()
                self.parent.app.load_games()
                self.parent.update_games_list()
            
            # 更新DOSBox路径
            new_dosbox_path = self.dosbox_entry.get_text()
            if new_dosbox_path and os.path.exists(new_dosbox_path) and os.access(new_dosbox_path, os.X_OK):
                self.parent.app.dosbox_path = new_dosbox_path
            
            # 保存默认视图设置
            new_view_mode = 'list' if self.list_radio.get_active() else 'grid'
            if new_view_mode != self.parent.app.view_mode:
                self.parent.app.view_mode = new_view_mode
                self.parent.app.save_config()
                self.parent.on_view_mode_changed(
                    self.parent.list_view_btn if new_view_mode == 'list' else self.parent.grid_view_btn,
                    new_view_mode
                )
            
            # 处理语言设置变更
            selected_lang = self.lang_combo.get_active_id()
            if selected_lang:
                self.parent.app.change_language(selected_lang)
        
        self.destroy()

class AboutDialog(Gtk.Dialog):
    def __init__(self, parent):
        self.trans = parent.app.translator
        super().__init__(
            transient_for=parent, 
            title=self.trans.get("about_title")
        )
        self.set_default_size(300, 200)
        
        self.add_button(self.trans.get("ok"), Gtk.ResponseType.OK)
        self.set_default_response(Gtk.ResponseType.OK)
        
        content_area = self.get_content_area()
        content_area.set_spacing(12)
        content_area.set_margin_start(12)
        content_area.set_margin_end(12)
        content_area.set_margin_top(12)
        content_area.set_margin_bottom(12)
        
        name_label = Gtk.Label()
        name_label.set_markup(f"<b>{self.trans.get('app_title')}</b>")
        name_label.set_xalign(0.5)
        
        version_label = Gtk.Label(label=self.trans.get("version"))
        version_label.set_xalign(0.5)
        
        copyright_label = Gtk.Label(label=self.trans.get("copyright"))
        copyright_label.set_xalign(0.5)
        
        desc_label = Gtk.Label(
            label=self.trans.get("description")
        )
        desc_label.set_xalign(0.5)
        desc_label.set_line_wrap(True)
        desc_label.set_max_width_chars(40)
        
        content_area.pack_start(name_label, False, False, 0)
        content_area.pack_start(version_label, False, False, 0)
        content_area.pack_start(copyright_label, False, False, 0)
        content_area.pack_start(desc_label, False, False, 0)
        
        self.show_all()

if __name__ == "__main__":
    print("Starting PyDOSBox application...")
    try:
        app = PyDOSBox()
        print("Application instance created")
        sys.exit(app.run(sys.argv))
    except Exception as e:
        print(f"Fatal error: {str(e)}")
        import traceback
        traceback.print_exc()
    